package com.ler.yrmall.product.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ler.yrmall.enums.BasicStatusEnum;
import com.ler.yrmall.product.entity.AttrAttrGroupRelationEntity;
import com.ler.yrmall.product.entity.AttrEntity;
import com.ler.yrmall.product.entity.AttrGroupEntity;
import com.ler.yrmall.product.entity.CategoryEntity;
import com.ler.yrmall.product.form.AttrForm;
import com.ler.yrmall.product.mapper.AttrMapper;
import com.ler.yrmall.product.service.AttrAttrgroupRelationService;
import com.ler.yrmall.product.service.AttrGroupService;
import com.ler.yrmall.product.service.AttrService;
import com.ler.yrmall.product.service.CategoryService;
import com.ler.yrmall.product.vo.AttrVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author leron
 */
@Slf4j
@Service
public class AttrServiceImpl extends ServiceImpl<AttrMapper, AttrEntity> implements AttrService {

    @Resource
    private AttrAttrgroupRelationService attrAttrgroupRelationService;

    @Resource
    private CategoryService categoryService;

    @Resource
    private AttrGroupService attrGroupService;

    @Override
    public List<AttrVO> list(AttrForm request) {
        List<AttrEntity> list = this.list(Wrappers.<AttrEntity>lambdaQuery()
                .eq(AttrEntity::getAttrType, request.getAttrType())
                .eq(request.getCategoryId() != null, AttrEntity::getCategoryId, request.getCategoryId()));
        List<Long> categoryIds = list.stream().map(AttrEntity::getCategoryId).collect(Collectors.toList());

        if (categoryIds.isEmpty()) {
            return BeanUtil.copyToList(list,AttrVO.class);
        }

        Map<Long, CategoryEntity> categoryMap = categoryService.list(Wrappers.<CategoryEntity>lambdaQuery()
                        .in(CategoryEntity::getId, categoryIds)).stream()
                .collect(Collectors.toMap(CategoryEntity::getId, Function.identity()));

        if (AttrEntity.AttrType.SALE.getCode().equals(request.getAttrType())) {
            return list.stream().map(item -> {
                AttrVO vo = BeanUtil.copyProperties(item, AttrVO.class);
                vo.setCategoryName(categoryMap.get(item.getCategoryId()).getName());
                return vo;
            }).collect(Collectors.toList());
        }

        return BeanUtil.copyToList(list,AttrVO.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveAttr(AttrForm attr) {
        AttrEntity attrEntity = new AttrEntity();
        BeanUtils.copyProperties(attr, attrEntity);
        this.save(attrEntity);
        if (attr.getAttrType().equals(AttrEntity.AttrType.BASIC.getCode())) {
            AttrAttrGroupRelationEntity attrAttrgroupRelationEntity = new AttrAttrGroupRelationEntity();
            attrAttrgroupRelationEntity.setAttrId(attrEntity.getId());
            attrAttrgroupRelationEntity.setAttrGroupId(attr.getAttrGroupId());
            attrAttrgroupRelationService.save(attrAttrgroupRelationEntity);
        }
    }

    @Override
    public IPage<AttrVO> find(AttrForm form) {
        IPage<AttrEntity> page = this.page(form.getPage(), Wrappers.<AttrEntity>lambdaQuery()
                .eq(AttrEntity::getAttrType, form.getAttrType())
                .eq(form.getCategoryId() != null, AttrEntity::getCategoryId, form.getCategoryId()));

        List<Long> categoryIds = page.getRecords().stream().map(AttrEntity::getCategoryId).collect(Collectors.toList());

        if (categoryIds.isEmpty()) {
            return page.convert(item -> BeanUtil.copyProperties(item, AttrVO.class));
        }

        Map<Long, CategoryEntity> categoryMap = categoryService.list(Wrappers.<CategoryEntity>lambdaQuery()
                        .in(CategoryEntity::getId, categoryIds)).stream()
                .collect(Collectors.toMap(CategoryEntity::getId, Function.identity()));

        if (AttrEntity.AttrType.SALE.getCode().equals(form.getAttrType())) {
            // 关联分类
            return page.convert(item -> {
                AttrVO vo = BeanUtil.copyProperties(item, AttrVO.class);
                vo.setCategoryName(categoryMap.get(item.getCategoryId()).getName());
                return vo;
            });
        }

        List<AttrEntity> records = page.getRecords();
        List<Long> attrIds = records.stream().map(AttrEntity::getId).collect(Collectors.toList());

        if (attrIds.isEmpty()) {
            return page.convert(item -> BeanUtil.copyProperties(item, AttrVO.class));
        }

        Map<Long, AttrAttrGroupRelationEntity> relationMap = attrAttrgroupRelationService.list(Wrappers.<AttrAttrGroupRelationEntity>lambdaQuery()
                        .in(AttrAttrGroupRelationEntity::getAttrId, attrIds)).stream()
                .collect(Collectors.toMap(AttrAttrGroupRelationEntity::getAttrId, Function.identity()));

        List<Long> groupIds = relationMap.values().stream().map(AttrAttrGroupRelationEntity::getAttrGroupId).collect(Collectors.toList());

        if (groupIds.isEmpty()) {
            return page.convert(item -> BeanUtil.copyProperties(item, AttrVO.class));
        }

        Map<Long, AttrGroupEntity> groupMap = attrGroupService.list(Wrappers.<AttrGroupEntity>lambdaQuery().in(AttrGroupEntity::getId, groupIds))
                .stream().collect(Collectors.toMap(AttrGroupEntity::getId, Function.identity()));


        return page.convert(item -> {
            AttrAttrGroupRelationEntity relation = relationMap.get(item.getId());
            AttrVO vo = new AttrVO();
            BeanUtils.copyProperties(item, vo);
            if (relation == null) {
                return vo;
            }
            AttrGroupEntity groupEntity = groupMap.get(relation.getAttrGroupId());
            CategoryEntity categoryEntity = categoryMap.get(groupEntity.getCategoryId());
            vo.setCategoryName(categoryEntity.getName());
            vo.setGroupName(groupEntity.getName());
            return vo;
        });
    }

    @Override
    public List<Long> filterSearchAttrIds(List<Long> attrIds) {
        return this.list(Wrappers.<AttrEntity>lambdaQuery()
                .in(AttrEntity::getId,attrIds)
                .eq(AttrEntity::getSearchType, BasicStatusEnum.SystemEnableStatus.ENABLED.getCode()))
                .stream().map(AttrEntity::getId)
                .collect(Collectors.toList());
    }


    @Override
    public AttrVO getVoById(Long attrId) {
        AttrEntity entity = this.getById(attrId);
        AttrVO target = new AttrVO();
        BeanUtils.copyProperties(entity, target);
        AttrAttrGroupRelationEntity relationEntity =
                attrAttrgroupRelationService.getOne(Wrappers.<AttrAttrGroupRelationEntity>lambdaQuery().eq(AttrAttrGroupRelationEntity::getAttrId, attrId));
        if (relationEntity != null) {
            target.setAttrGroupId(relationEntity.getAttrGroupId());
        }
        Long level3 = target.getCategoryId();
        Long[] categoryPath = categoryService.getCategoryPath(level3);
        target.setCategoryPath(Arrays.asList(categoryPath));
        return target;
    }
}